package com.zhdl.hardware.io.io_socket.service.impl;


import cn.hutool.json.JSONUtil;
import com.google.common.primitives.Bytes;
import com.zhdl.common.ytools.callback.CommonCallback;
import com.zhdl.hardware.io.io_socket.request.IOMemoryReq;
import com.zhdl.hardware.io.io_socket.response.IOSseEmitterVO;
import com.zhdl.hardware.io.io_socket.service.IOWebsocketService;
import com.zhdl.hardware.io.smartLink.repository.IOCmdHandleDao;
import com.zhdl.websocket.service.WebSocketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Slf4j
@Service
public class IOWebsocketServiceImpl implements IOWebsocketService {

    @Resource
    public WebSocketService webSocketService;
    @Resource
    public ThreadPoolTaskScheduler taskScheduler1;
    @Resource
    public IOCmdHandleDao ioCmdHandleDao;

    public IOMemoryReq ioMemoryReq = new IOMemoryReq();
    public IOSseEmitterVO ioSseEmitterVO = new IOSseEmitterVO();
    private CommonCallback<List<Byte>> io01Callback;
    private CommonCallback<List<Byte>> io02Callback;

    /**
     * 将byte转换为一个长度为8的byte数组，数组每个值代表bit
     */
    public static Byte[] getBitArray(byte b) {
        Byte[] array = new Byte[8];
        for (int i = 7; i >= 0; i--) {
            array[i] = (byte) (b & 1);
            b = (byte) (b >> 1);
        }
        return array;
    }

    @Override
    public void setIo01Callback(CommonCallback<List<Byte>> io01Callback) {
        this.io01Callback = io01Callback;
    }

    @Override
    public void setIo02Callback(CommonCallback<List<Byte>> io02Callback) {
        this.io02Callback = io02Callback;
    }

    @Override
    public IOSseEmitterVO getIoSseEmitterVO() {
        return ioSseEmitterVO;
    }

    /**
     * List<Byte> to str
     *
     * @param bytes 字节数组
     * @return /
     */
    public String byteArrayToStr(List<Byte> bytes) {

        byte[] array = Bytes.toArray(bytes);
        StringBuffer stringBuffer = new StringBuffer();

        for (byte b : array) {
            stringBuffer.append(b);
        }

        return stringBuffer.toString();
    }

    /**
     * IO-初始化
     */
    @Override
    public void ioInit() {
        taskScheduler1.scheduleWithFixedDelay(() -> {
            ioCmdHandleDao.ioReadCoilSignal("16", bytes -> {
                /* 获取当前指令返回的数据 */
                /* 对返回的数据进行处理 - 每八位进行高低位反转 */
                List<Byte> ioList = new ArrayList<>();
                for (byte b : bytes) {
                    Byte[] bitArray = getBitArray(b);
                    ioList.addAll(Arrays.asList(bitArray));
                }
                String io01 = byteArrayToStr(ioList);
                ioMemoryReq.setCoilIO(io01);
                if (io01Callback != null) {
                    io01Callback.statusCallback(ioList);
                }
                log.info("当前IO线圈状态为:" + ioList);
            });
            ioCmdHandleDao.ioReadDiscreteSignal("16", bytes -> {
                /* 获取当前指令返回的数据 */
                /* 对返回的数据进行处理 - 每八位进行高低位反转 */
                List<Byte> ioList = new ArrayList<>();
                for (byte b : bytes) {
                    Byte[] bitArray = getBitArray(b);
                    ioList.addAll(Arrays.asList(bitArray));
                }
                String io02 = byteArrayToStr(ioList);
                ioMemoryReq.setSensorIO(io02);
                if (io02Callback != null) {
                    io02Callback.statusCallback(ioList);
                }
                log.info("当前IO离散量状态为:" + ioList);
            });
        }, 100);
        taskScheduler1.scheduleWithFixedDelay(() -> {
            ioSseEmitterVO.setIoMemoryReq(ioMemoryReq);
            String jsonStr = JSONUtil.toJsonStr(ioSseEmitterVO);
            webSocketService.sendMessage(jsonStr);
            log.info("IO信号为:" + jsonStr);
        }, 1000);
    }


    /**
     * IO读取-判断结果是否到位
     */
    public void ioRead02Result(int sensorId, int value, int timeout, CommonCallback<String> callback) {
        /* 声明循环次数 */
        final int[] times = new int[]{0};
        /* 声明scheduledFuture的key */
        String key = "io" + sensorId;

        taskScheduler1.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {


            }
        }, 100);
    }

}
